package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.ErrorResult;
import com.itheima.vo.UserInfoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class UserManager {

    @DubboReference //远程注入
    UserService userService;

    @Autowired
    SmsTemplate smsTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    HuanXinTemplate huanXinTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    public Long save(User user) {
        return userService.save(user);
    }

    public User findByPhone(String phone) {
        return userService.findByPhone(phone);
    }

    public ResponseEntity sendCode(String phone) {
        try {
            //1.生成验证码
            String code = RandomUtil.randomNumbers(6);
            //TODO 现在开发阶段,只需要固定验证码为123456
            code = ConstantUtil.INIT_PASSWORD;

            //int i = 1/0;

            //2.调用smsTemplate发送短信,
            //TODO 现在开发阶段,以后项目上线了再开启这个注释
            //smsTemplate.sendSms(code);

            //3.将验证码放入redis中,且设置时效5分钟
            //stringRedisTemplate.opsForValue().set("sms:"+phone,code, Duration.ofMinutes(5));
            stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE+phone,code, Duration.ofMinutes(5));

            return ResponseEntity.ok(null);//相当于返回200
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(500).body(ErrorResult.sendSmsError());
        }
    }

    public ResponseEntity regAndLogin(Map<String, String> map) {
        //1.获取用户提交过来的手机号和验证码
        String phone = map.get("phone");
        String verificationCode = map.get("verificationCode");

        //2.判断用户的验证码是否和redis中一致
        String redisCode = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        //3.若不一致,生成响应,提示验证码输出错误
        if (!StrUtil.equals(verificationCode,redisCode)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }

        //4.若一致,通过手机号查询用户,返回user
        User user = userService.findByPhone(phone);

        //5.判断用户是否存在
        boolean isNew;
        //5.1.若存在,就是老用户 isNew=false
        if (user != null) {
            isNew = false;
        }else {
            //5.2.若不存在,就是新用户 isNew=true,保存用户
            isNew = true;

            //保存用户
            user = new User();
            user.setMobile(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);
            Long id = userService.save(user);
            user.setId(id);

            //向环信上注册此用户
            huanXinTemplate.register("HX"+id);
        }

        //6.生成token,为了以后登录方便,将用户token和用户信息放入redis,设置时效30天.删除短信验证码
        user.setPassword(null);
        String token = JwtUtil.createToken(BeanUtil.beanToMap(user));

        //将token放入redis中
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN+token, JSON.toJSONString(user),Duration.ofDays(30));
        //删除短信验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE+phone);

        //7.返回客户端数据
        Map<String,Object> responseMap = new HashMap<>();
        responseMap.put("isNew",isNew);
        responseMap.put("token",token);

        //8.封装log对象,向mq发送日志对象
        Log log = new Log();
        log.setUserId(user.getId());
        log.setLogTime(DateUtil.formatDate(new Date()));
        log.setPlace("顺义");
        log.setEquipment("华为p60");
        log.setType(isNew?"0102":"0101");

        //rabbitTemplate.convertAndSend("","tanhua.log",log);
        rabbitTemplate.convertAndSend("tanhua.log",log);

        return ResponseEntity.ok(responseMap);
    }

    @DubboReference
    UserInfoService userInfoService;

    public ResponseEntity saveUserInfo(UserInfo userInfo, String token) {
       /* //1.通过token去redis中获取用户
        User user = findUserFormToken(token);

        //2.若用户没有获取到,返回401
        if (null == user) {
            return ResponseEntity.status(401).body(null);
        }*/

        User user = UserHolder.get();

        //3.给userInfo设置用户id
        userInfo.setId(user.getId());

        //4.调用service完成保存操作
        userInfoService.save(userInfo);

        return ResponseEntity.ok(null);
    }


    //通过token去redis中获取用户
    public User findUserFormToken(String token){
        if (StrUtil.isNotBlank(token)) {
            String value = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);

            if (StrUtil.isNotBlank(value)) {
                return JSON.parseObject(value, User.class);
            }
        }

        return null;
    }

    @Autowired
    AipFaceTemplate aipFaceTemplate;

    @Autowired
    OssTemplate ossTemplate;

    public ResponseEntity saveOrUpdatePhoto(MultipartFile headPhoto, String token) throws IOException {
        //1.通过token去redis中获取用户
        User user = findUserFormToken(token);

        //2.若用户没有获取到,返回401
        if (null == user) {
            return ResponseEntity.status(401).body(null);
        }

        //3.判断图片是否是人脸,若不是返回错误
        if (!aipFaceTemplate.detect(headPhoto.getBytes())) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //4.若是,就需要将图片上传到oss
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //5.给userinfo设置id和头像地址
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        //头像
        userInfo.setAvatar(url);
        //封面
        userInfo.setCoverPic(url);

        //6.远程调用service完成更新操作
        userInfoService.update(userInfo);
        return ResponseEntity.ok(null);
    }

    public ResponseEntity findUserInfoById(Long userID) {
        //1.远程调用service完成查询操作,返回UserInfo对象
        UserInfo userInfo = userInfoService.findByUserId(userID);

        //2.将userInfo封装成UserInfoVo对象然后返回
        UserInfoVo vo = new UserInfoVo();

        //我们用spring的工具类,目标对象在后面
        BeanUtils.copyProperties(userInfo,vo);

        return ResponseEntity.ok(vo);
    }

    public ResponseEntity updateUserInfo(UserInfo userInfo, String token) {
        //1.通过token去redis中获取用户
        User user = findUserFormToken(token);

        //2.若用户没有获取到,返回401
        if (null == user) {
            return ResponseEntity.status(401).body(null);
        }

        //3.若不为空,给userInfo设置用户id
        userInfo.setId(user.getId());

        //4.远程调用service完成更新操作
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }
}
